package algorithms;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map.Entry;

import puppy.graph.AgeAggregator;
import puppy.graph.CreateGraphDirected;
import puppy.graph.CreateGraphOnlyTags;
import puppy.graph.DeliciousEdge;
import puppy.graph.DeliciousEdgeSimple;
import puppy.graph.DeliciousEdgeSimpleTransformer;
import puppy.graph.DeliciousEdgeTransformer;
import puppy.graph.DeliciousNode;
import puppy.graph.DeliciousNodeSimple;
import puppy.graph.DeliciousNodeSimpleTransformer;
import puppy.graph.DeliciousNodeTransformer;
import util.hashing.Sorting;
import util.ranker.RankingService;
import edu.uci.ics.jung.algorithms.scoring.PageRank;

public class PageRankSuggestionsNode implements RankingService{

	CreateGraphOnlyTags graph = null;
	
	double query_total=0;
	
	DeliciousEdgeSimpleTransformer edge_transformer = null;
	DeliciousNodeTransformer node_transformer = null;
	AgeAggregator agg = null;
	public double epsilon=0.000001;
	public double alpha=0.2 ;
	public int max_iterations=3;
	public double n_gram_weight=2;
	public int mimimum_length_ngram=2;

	private int results_printed=100;

	private Float query_threshold_freq=3f;
	
	public PageRankSuggestionsNode(String path, AgeAggregator agg) {
		this.agg= agg;
		graph =new CreateGraphOnlyTags();
		graph.initGraph(path);
	
		
	}

	
	public float calulateConditionalProb(Hashtable<String,Float>q){
		
		float p=0f;
		
		
		return p;
		
		
	}
	
	public Hashtable<String, Float> generatePossibleTokensNGram(String query_text) {
		Hashtable<String, Float> h = new Hashtable<String, Float>();

		String ngram = query_text.replace(" ", "_");
		String t[] = ngram.split("_");

		if (graph.tag_names.containsKey(ngram)) {

			float prior =0;
			h.put(ngram, 0f);

		}

		HashSet<String> tokens = new HashSet<String>();
		for (int i = 0; i < t.length; i++) {

			
			if (i + 2 < t.length) {

				String m = t[i] + "_" + t[i + 1] + "_" + t[i + 2];
				if (graph.tag_names.containsKey(m) && !tokens.contains(t[i]) && !tokens.contains(t[i+1]) &&!tokens.contains(t[i+2]) ) {

					tokens.add(t[i]);
					tokens.add(t[i+1]);
					tokens.add(t[i+2]);
					h.put(m, 0f);
				}

			}
			
			
			if (i + 1 < t.length) {

				String m = t[i] + "_" + t[i + 1];
				if (graph.tag_names.containsKey(m) && !tokens.contains(t[i]) && !tokens.contains(t[i+1])) {

					tokens.add(t[i]);
					tokens.add(t[i+1]);
					
					h.put(m, 0f);
				}

			}
			if (graph.tag_names.containsKey(t[i]) && !tokens.contains(t[i])) {
			
				tokens.add(t[i]);
				
				h.put(t[i], 0f);
			}

			

			

		}
		
		return h;
	}
	

	
public ArrayList<Entry<String, Float>> performPageRanKAbsorving(Hashtable<String,Float>q, String query, int limit){
		
		
	//create list of query n_gram phrases
			// star_wars --> star_wars_lego
			// star_wars_lego --> star_wars, star_wars_games, etc
			//q=generatePossibleTokensNGram(query);
			DeliciousNodeSimpleTransformer transformer = 
					new DeliciousNodeSimpleTransformer(q,graph,query, n_gram_weight,  mimimum_length_ngram);
		
		
		
			edge_transformer = 
					new DeliciousEdgeSimpleTransformer();
	
		 
		 RandomWalkAbsorvingNN<DeliciousNodeSimple, DeliciousEdgeSimple> ranker = 	
								new RandomWalkAbsorvingNN
						(graph.graph,edge_transformer,transformer, alpha);
		ranker.initModifiers(transformer, edge_transformer,q);
		 
		ranker.setTolerance(epsilon);
		
		ranker.acceptDisconnectedGraph(true);
		ranker.setMaxIterations(max_iterations);
		
		//ranker.setEdgeWeights(edge_weights)
		System.out.println("Running page rank.." + "\t"+ q);
		ranker.evaluate();	
		
		Enumeration<Integer> nodes = graph.tag_names.keys();
		Hashtable<String, Float> scores = new Hashtable<String, Float>();
		while (nodes.hasMoreElements()) {
			Integer node = nodes.nextElement();

			DeliciousNodeSimple no = graph.tag_names.get(node);

			if (no.name.equals("") || tagInQuery(no.name,query)) {
				
				continue;
			}
			
		
			double s = ranker.getVertexScore(no);
			scores.put(no.name, (float) s);

		

		}

		Iterator<Entry<String, Float>> tuples = Sorting.getTopN_Tuples(scores, false, 150);
		HashSet<String> temp = new HashSet<String>();
	
		int i=0;
		while (tuples.hasNext() ) {
			Entry<String, Float> t = tuples.next();
			
			if(!wasSuggestionsSeenBefore(temp,t.getKey())){
			i++;
		//	results.add(t);
			if(i<results_printed)
				System.out.println(query+ "\t"+ t.getKey() + "\t" + i +"\t" + t.getValue());
			temp.add(t.getKey());
			}
		}
		
		
		
		//clean modifiers
		tuples=null;
		temp.clear();
		temp=null;
		transformer.clean();
		transformer=null;
		
		
		q.clear();
		q=null;
		
		return null;
	}
	
	
private boolean wasSuggestionsSeenBefore(HashSet<String> temp, String key) {
		// TODO Auto-generated method stub

		if(temp.contains(key+ "s")) return true;
		
		if(temp.contains(key.substring(0,key.length()-1))) return true;
	
		return false;
	}





 public Hashtable<String,Float> reRankQueryTerms(Hashtable<String,Float> q, String query){
	 
	 Hashtable<String,Float> re = new Hashtable<String,Float>();
	 
	 Enumeration<String> keys = q.keys();
	 
	 while(keys.hasMoreElements()){
		 
		 
	 }
	 
	 return re;
	 
	 
 }
	private boolean tagInQuery(String name, String query) {
		// TODO Auto-generated method stub

		//example tag star   query star_wars
		
		query = query.replaceAll("_", " ");
		
		name = name.replaceAll("_", " ");
		
		String[] query_tokens = query.split(" ");
		String[] tag_tokens = name.split(" ");
		
		
		
		if(name.contains(query) && name.length()>query.length()) return false;
		
		if(query.equals(name)){
			
			
			return true;
	
		} 
		
		int matches=0;
		for(int i=0; i< tag_tokens.length; i++){
			
			for(int j=0; j<query_tokens.length; j++){
				
				if(tag_tokens[i].equals(query_tokens[j])){
				
					matches++;
					
				}
			}
		}
		
	
		if(matches>=tag_tokens.length) return true;
		
		return false;
	}
	
	

	public static void main(String argvs[]) {

		String prefix = "/Users/sergioduarte/projects/data/graph/";

		String single_query="/Users/sergioduarte/projects/data/results/single_query/star_wars.txt";
		
		// String path =
		// "/media/sata__/data/delicious_graph/delicious_graphML_raw_ids_dmoz.txt";
		String path = prefix + "delicious_graphML_raw_ids_dmoz_youth.txt";
			
		AgeAggregator	agg= new AgeAggregator(true, true, true, true, false, false, true);
		
		PageRankSuggestionsNode page = new PageRankSuggestionsNode(path,agg);
	
	
		//page.performPageRankWithPriors();
		
		//page.performPageRank();
	}

	
	
	public Hashtable<String,Float> calculateQueryRatios(Hashtable<String, Float> q){
		
		Hashtable<String, Float> qq= new Hashtable<String, Float> ();
		
		
		Enumeration<String> keys = q.keys();
		float total=0.0f;
		while(keys.hasMoreElements()){
			String element  = keys.nextElement();
			
			if(element.contains("school")){
				
				
				System.out.println(graph.tag_names.containsKey(element) + "---\t "+ element);
			}
			if(graph.tag_names.containsKey(element)){
			total= total+ q.get(element);
			}
			
		}
		
		keys=q.keys();
		
		while(keys.hasMoreElements()){
			String tag= keys.nextElement();
			if(graph.tag_names.containsKey(tag)){
				if (q.get(tag)>=query_threshold_freq){
				
				qq.put(tag, q.get(tag)/total);		
				}
			}
			
			
		//	System.out.println(tag + "\t"+ qq.get(tag));
		}
		
		return qq;
	}	
	@Override
	public ArrayList<Entry<String, Float>> rankQuery(
			String query, Hashtable<String,Float>q, int limit) {
		
		
		Hashtable<String, Float> qq = calculateQueryRatios(q);
		// TODO Auto-generated method stub
	//	return performPageRankWithPriors(q,query,limit);
		
		
		return performPageRanKAbsorving(qq,query,limit);
		//return null;
	}


	@Override
	public ArrayList<Entry<String, Float>> rankQuery(String query, int limit) {
		// TODO Auto-generated method stub
		return null;
	}

}